package com.gmu.uav;

import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.text.method.ScrollingMovementMethod;
import android.hardware.*;


public class ControllerActivity extends Activity implements SensorEventListener{
	
	private ArduinoConnection arduinoConn = null;
	private MediaPlayer mediaPlayer = null;
	private ToggleButton bluetoothConnect_tb = null;
	private ToggleButton mcuConnect_tb = null;
    private SensorManager mSensorManager = null;
    private Sensor mGyroscope = null;
    private Sensor mOrientation = null;
    private Sensor mAccelerometer = null;
    private TextView mLeftAileron_tv = null;
    private TextView mRightAileron_tv = null;
    private TextView mThrust_tv = null;
    private SeekBar leftAileronSeek = null;
    private SeekBar rightAileronSeek = null;
    private SeekBar thrustSeek = null;
	private List<Sensor> mSensorList = null;
	private StringBuffer logBuffer = new StringBuffer();
	private boolean gyroAvailable = false;
	private boolean orientationAvailable = false;
	private boolean accelerometerAvailable = false;
	private boolean uav_connected = false;
	private boolean uav_manualControl = false;
	private static final int REQUEST_ENABLE_BT = 1;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.controller);
        
        arduinoConn = (ArduinoConnection) getApplication();
        
        bluetoothConnect_tb = (ToggleButton)findViewById(R.id.toggleButtonBluetooth);
        mcuConnect_tb = (ToggleButton)findViewById(R.id.toggleButtonConnect);
        
        mLeftAileron_tv = (TextView)findViewById(R.id.leftAileron_tv);
        mRightAileron_tv = (TextView)findViewById(R.id.rightAileron_tv);
        mThrust_tv = (TextView)findViewById(R.id.thrust_tv);
        
        //SeekBar Setup
        leftAileronSeek = (SeekBar)findViewById(R.id.leftAileron);
        rightAileronSeek = (SeekBar)findViewById(R.id.rightAileron);
        thrustSeek = (SeekBar)findViewById(R.id.thrust);
        
        //Grab Sensor Manager Object
        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        
        //Popular List of Gyroscopes
        mSensorList = mSensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
        
        addToLog("Detected " + mSensorList.size() + " gyroscope sensor(s).\n" );
        
        if(mSensorList.size() > 0)
        {
        	gyroAvailable = true;
        	
        	for(int i = 0; i < mSensorList.size(); i++)
        	{
        		Sensor gyro = mSensorList.get(i);
        		
        		addToLog("Gyro #" + i + " name: " + gyro.getName());
        		addToLog("Gyro #" + i + " vendor: " + gyro.getVendor());
        		addToLog("Gyro #" + i + " max range: " + gyro.getMaximumRange());
        		addToLog("Gyro #" + i + " min delay: " + gyro.getMinDelay() + " μs");
        		addToLog("Gyro #" + i + " power: " + gyro.getPower() + " mA");
        		addToLog("Gyro #" + i + " resolution: " + gyro.getResolution() + "\n");
        	}
        }

        //Populate List of Orientation Sensors
        mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
        
        addToLog("Detected " + mSensorList.size() + " orientation sensor(s).\n" );
        
        if(mSensorList.size() > 0)
        {
        	orientationAvailable = true;
        	
        	for(int i = 0; i < mSensorList.size(); i++)
        	{
        		Sensor orientationSensor = mSensorList.get(i);
        		
        		addToLog("Orientation #" + i + " name: " + orientationSensor.getName());
        		addToLog("Orientation #" + i + " vendor: " + orientationSensor.getVendor());
        		addToLog("Orientation #" + i + " max range: " + orientationSensor.getMaximumRange());
        		addToLog("Orientation #" + i + " min delay: " + orientationSensor.getMinDelay() + " μs");
        		addToLog("Orientation #" + i + " power: " + orientationSensor.getPower() + " mA");
        		addToLog("Orientation #" + i + " resolution: " + orientationSensor.getResolution() + "\n");
        	}
        }
        
        //Populate List of Accelerometer Sensors
        mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
        
        addToLog("Detected " + mSensorList.size() + " accelerometer sensor(s).\n" );
        
        if(mSensorList.size() > 0)
        {
        	accelerometerAvailable = true;
        	
        	for(int i = 0; i < mSensorList.size(); i++)
        	{
        		Sensor accelerometerSensor = mSensorList.get(i);
        		
        		addToLog("Accelerometer #" + i + " name: " + accelerometerSensor.getName());
        		addToLog("Accelerometer #" + i + " vendor: " + accelerometerSensor.getVendor());
        		addToLog("Accelerometer #" + i + " max range: " + accelerometerSensor.getMaximumRange());
        		addToLog("Accelerometer #" + i + " min delay: " + accelerometerSensor.getMinDelay() + " μs");
        		addToLog("Accelerometer #" + i + " power: " + accelerometerSensor.getPower() + " mA");
        		addToLog("Accelerometer #" + i + " resolution: " + accelerometerSensor.getResolution() + "\n");
        	}
        }
       
        //Grab Sensor Objects
        mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        
	    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
	    
	    if(gyroAvailable != true)
	    {
	    	Toast.makeText(getApplicationContext(), "Gyroscope not available! Control of UAV not possible!", Toast.LENGTH_LONG).show();
	    }
	    
	    thrustSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() 
	    {
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				mThrust_tv.setText("Thrust: " + progress + "%");
				
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub
				
			}
	    	
	    });
    }
	
	@Override
	protected void onResume()
	{
		super.onResume();
		
		 mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_UI);
		 mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_UI);
		 mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
		 
		 if(arduinoConn.isBluetoothConnected())
		 {
			 bluetoothConnect_tb.setChecked(true);
		 }
		 else
		 {
			 bluetoothConnect_tb.setChecked(false);
		 }
	
	}
	
	@Override
	protected void onPause() 
	{
        super.onPause();
        mSensorManager.unregisterListener(this);
    }
	
	public void addToLog(String message)
	{
		logBuffer.append("\n" + message);
	}

	public void bluetoothConnect(View view)
	{
		if(arduinoConn.isBluetoothConnected())
		{
			arduinoConn.disableBluetooth();
			
			mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.bluetooth_disabled);
			mediaPlayer.start();
		}
		else
		{ 
			arduinoConn.enableBluetooth(this);
		}
	}
	
	public void connectToMCU(View view)
	{
		if( ! arduinoConn.isBluetoothConnected() )
		{
			mcuConnect_tb.setChecked(false);
			
			mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.bluetooth_must_be_connected_first);
			mediaPlayer.start();
			
			return;
		}
		
		if(!uav_connected)
		{		
			uav_connected = true;
			mcuConnect_tb.setChecked(true);
			
			mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.connected);
			mediaPlayer.start();
		}
		else
		{
			uav_connected = false;
			mcuConnect_tb.setChecked(false);
			
			mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.disconnected);
			mediaPlayer.start();
		}
		
	}
	
	public void manualControlToggle(View view)
	{
		if(!uav_manualControl)
		{
			uav_manualControl = true;
			
			mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.manaul_control_on);
			mediaPlayer.start();
		}
		else
		{
			uav_manualControl = false;
			
			mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.manual_control_off);
			mediaPlayer.start();
		}
		
	}
	
	@Override
	public void onStop()
	{
		super.onStop();
		
		if(mediaPlayer != null)
		{
			mediaPlayer.release();
			mediaPlayer = null;
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.global_menu, menu);
	    
	    return true;
	}
		
	@Override
	public boolean onOptionsItemSelected(MenuItem item) 
	{
	    switch (item.getItemId()) 
	    {
	        case R.id.switchToMap:
	        	
	        	startActivity(new Intent(getApplicationContext(), MapViewActivity.class));
	            return true;
	            
	        case R.id.switchToFeed:
	        	
	        	startActivity(new Intent(getApplicationContext(), VideoActivity.class));
		        return true;
	          
	        case R.id.switchToController:
	        	return true;
	        	
	        default:
	            return super.onOptionsItemSelected(item);
	    }
	}

	public void onAccuracyChanged(Sensor arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}

	public void onSensorChanged(SensorEvent event) 
	{
		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) 
		{
			  // Axis of the rotation sample, not normalized yet.					
              float axisX = event.values[0];
              float axisY = event.values[1];
              float axisZ = event.values[2];
              
              if(Math.abs(axisY) > 2 ) //Turning is more important than altitude
              {       
	              if(axisY > 0) // Turning Right
	              {
	            	  mLeftAileron_tv.setText("Left Aileron: " + ((int)axisY * 3) + "°");
	            	  leftAileronSeek.setProgress(30 + ((int)axisY * 3));
	              }
	              
	              if(axisY < 0) // Turning Left
	              {
	            	  mRightAileron_tv.setText("Right Aileron: " + (Math.abs((int)axisY * 3)) + "°");
	            	  rightAileronSeek.setProgress(30 + Math.abs(((int)axisY * 3)));
	              }
	              
	              return;
              }
              
              if(axisZ > 0 ) // Lower Altitude
              {
            	  mLeftAileron_tv.setText("Left Aileron: " + ((int)axisZ * 3) + "°");
            	  leftAileronSeek.setProgress(30 + ((int)axisZ * 3));
            	  
            	  mRightAileron_tv.setText("Right Aileron: " + ((int)axisZ * 3) + "°");
            	  rightAileronSeek.setProgress(30 + ((int)axisZ * 3));
              }
              
              if(axisZ < 0) // Gain Altitude
              {
            	  mLeftAileron_tv.setText("Left Aileron: " + ((int)axisZ * 3) + "°");
            	  leftAileronSeek.setProgress(30 + ((int)axisZ * 3));
            	  
            	  mRightAileron_tv.setText("Right Aileron: " + ((int)axisZ * 3) + "°");
            	  rightAileronSeek.setProgress(30 + ((int)axisZ * 3));            	  
              }
              
              //Log.i("UAV", "Axis X: " + axisX + " Axis Z: " + axisZ);
		}	
	}
	
	protected void onActivityResult (int requestCode, int resultCode, Intent data)
	{
		if(requestCode == REQUEST_ENABLE_BT)
		{
			if(resultCode == Activity.RESULT_OK)
			{
				mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.bluetooth_enabled);
				mediaPlayer.start();
			} 
			else if(resultCode == Activity.RESULT_CANCELED) 
			{
		
			}
		}
	}
}
